﻿using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Sgr.Application;
using Sgr.Application.Commands;
using Sgr.Application.ViewModels;
using Sgr.Domain.Repositories;
using Sgr.Domain.Uow;
using Sgr.Exceptions;
using Sgr.Identity;
using Sgr.Identity.Services;
using Sgr.Indentity.Application.ViewModels;
using Sgr.Modules;
using Sgr.Security.Tokens.Services;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;

namespace Sgr.Indentity.Application.Commands
{
    public class SecondPasswordVerifyCommondHandle
        : IdentityCommandHandleBase, IRequestHandler<SecondPasswordVerifyCommond, CommandResult<string>>
    {
        private readonly IdentityOptions _identityOptions;
        private readonly ISignatureChecker _signatureChecker;
        private readonly ITemporaryTokenService _temporaryTokenService;
        private readonly ICurrentUser _currentUser;

        public SecondPasswordVerifyCommondHandle(
            IAccountAuthService accountService,
            ISignatureChecker signatureChecker,
            ITemporaryTokenService temporaryTokenService,
            ICurrentUser currentUser,
            IHttpContextAccessor httpContextAccessor,
            IOptions<IdentityOptions> options)
            : base(accountService, httpContextAccessor)
        {
            _identityOptions = options?.Value ?? throw new ArgumentNullException(nameof(options));
            _temporaryTokenService = temporaryTokenService ?? throw new ArgumentNullException(nameof(temporaryTokenService));
            _currentUser = currentUser ?? throw new ArgumentNullException(nameof(currentUser));
            _signatureChecker = signatureChecker ?? throw new ArgumentNullException(nameof(signatureChecker));
        }

        public async Task<CommandResult<string>> Handle(SecondPasswordVerifyCommond request, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(request.Password))
                return CommandResult.Invalid<string>("密码不能为空!");

            // 检查签名
            if (_identityOptions.UseSignature)
            {
                string secretKey = $"{request.Password}";
                if (!_signatureChecker.VerifySignature(request.Signature, request.Timestamp, request.Nonce, secretKey, secretKey))
                    return CommandResult.Invalid<string>("参数签名验证失败!");
            }

            // 获取当前登录用户标识
            var userId = _currentUser.Id;
            if (string.IsNullOrEmpty(userId))
                return CommandResult.Invalid<string>("无法获取当前用户登录信息!");

            // 校验密码
            var result = await base._accountService.ValidateAccountPasswordAsync(userId, request.Password, cancellationToken);
            if (!result.IsComply)
                return CommandResult.Invalid<string>(result.Message);

            // 创建二次密码校验的令牌
            var token = await _temporaryTokenService.CreateAsync(
                tokenType: request.TokenType,
                deviceFingerprint: _currentUser.DeviceFingerprint,
                userId: userId,
                content: null,
                expirationMinutes: 5,
                cancellationToken: cancellationToken);

            return CommandResult.Success<string>(token.Code);
        }
    }
}